package service

import (
	"strings"

	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/httpmvc/service"
	"gorm.io/gorm"

	"ssforward/cmd/system"
	"ssforward/common/constant"
	"ssforward/common/dto"
	"ssforward/common/enums"
	"ssforward/common/utils"
	"ssforward/internal/data/clients"
	"ssforward/internal/data/handler"
	"ssforward/internal/forward/models"
	"ssforward/internal/forward/models/command"
	"ssforward/internal/forward/models/query"
)

type ForwardServer struct {
	serverModel *models.SysForwardServer
	serverRule  *models.SysForwardRule
	service.Service
}

func (d *ForwardServer) SetServerModel(m *models.SysForwardServer) *ForwardServer {
	d.serverModel = m
	return d
}

func (d *ForwardServer) SetServerRuleModel(m *models.SysForwardRule) *ForwardServer {
	d.serverRule = m
	return d
}

// 添加服务
func (d *ForwardServer) AddForwardServer(req *command.ForwardServerInsertReq) (err error, forwardServer models.SysForwardServer) {
	if err = req.Generate(&forwardServer); err != nil {
		return
	}
	err = d.Orm.Transaction(func(tx *gorm.DB) error {
		// 事务orm
		d.serverModel.Orm = tx
		// 启动客户端(mqtt/db)
		if forwardServer.Type == enums.Mqtt.Get().Value {
			if err = clients.InitMqClientItem(forwardServer); err != nil {
				return err
			} else {
				forwardServer.ConnectStatus = "true"
			}
		} else if forwardServer.Type == enums.Database.Get().Value {
			if err = clients.InitDbClientItem(forwardServer); err != nil {
				return err
			} else {
				forwardServer.ConnectStatus = "true"
			}
		}
		// 基本信息
		if err = d.serverModel.Add(&forwardServer); err != nil {
			return err
		}
		return nil
	})
	return
}

// 编辑服务
func (d *ForwardServer) EditForwardServer(req *command.ForwardServerEditReq) (err error, forwardServer models.SysForwardServer) {
	if err = d.serverModel.FindOne(&forwardServer, dto.MakeCondition(query.ForwardServerQuery{Id: req.Id})); err != nil {
		return
	}
	req.Generate(&forwardServer)
	err = d.Orm.Transaction(func(tx *gorm.DB) error {
		// 事务orm
		d.serverModel.Orm = tx
		// 启动客户端(mqtt/db)
		if forwardServer.Type == enums.Mqtt.Get().Value {
			// 先删
			clients.RemoveMqClientItem(enums.Mqtt.Get().Value + constant.MqttNumber + "-" + forwardServer.Id)
			// 后启
			if err = clients.InitMqClientItem(forwardServer); err != nil {
				return err
			} else {
				forwardServer.ConnectStatus = "true"
			}
		} else if forwardServer.Type == enums.Database.Get().Value {
			// 先删
			clients.RemoveDbClientItem(enums.Database.Get().Value + "-" + forwardServer.Id)
			// 后启
			if err = clients.InitDbClientItem(forwardServer); err != nil {
				return err
			} else {
				forwardServer.ConnectStatus = "true"
			}
		}
		// 基本信息
		if err = d.serverModel.Mod(&forwardServer); err != nil {
			return err
		}
		return nil
	})
	// 清理刷新配置缓存
	keyList := env.Cache.ScanKey(constant.ForwardConfigKey + "*")
	for _, key := range keyList {
		if err = env.Cache.Del(key); err == nil {
			constant.HasForwardConfigSn.Delete(strings.Split(key, ":")[1])
		}
	}
	system.InitForwardCache()
	return
}

// 删除服务
func (d *ForwardServer) DeleteServer(req *command.ServerDeleteReq) (err error) {
	idList := strings.Split(strings.ReplaceAll(req.Id, " ", ""), ",")
	if err = d.Orm.Transaction(func(tx *gorm.DB) error {
		d.serverRule.Orm = tx
		d.serverModel.Orm = tx
		// 删服务
		if err = d.serverModel.Delete(d.serverModel, dto.MakeCondition(query.ForwardServerQuery{IdIn: idList})); err != nil {
			return err
		}
		// 删规则
		ruleService := &ForwardRule{}
		ruleService.Orm = tx
		ruleService.Log = d.Log
		ruleService.SetServerRuleModel(d.serverRule)
		if err = ruleService.DeleteServerRule(&command.RuleDeleteReq{ServerId: req.Id}); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return
	}
	// 删除客户端
	for _, serverId := range idList {
		clients.RemoveMqClientItem(enums.Mqtt.Get().Value + constant.MqttNumber + "-" + serverId)
		clients.RemoveDbClientItem(enums.Database.Get().Value + "-" + serverId)
		// 删除转发明细
		_ = env.Cache.Del(constant.ForwardClientPrefix + serverId)
	}
	return
}

// 测试服务
func (d *ForwardServer) TestForwardServer(req *command.ForwardServerEditReq) (err error) {
	var forwardServer models.SysForwardServer
	if err = d.serverModel.FindOne(&forwardServer, dto.MakeCondition(query.ForwardServerQuery{Id: req.Id})); err != nil {
		return
	}
	if forwardServer.Type == enums.Mqtt.Get().Value {
		err = clients.TestMqttClientItem(forwardServer)
	} else if forwardServer.Type == enums.Database.Get().Value {
		err = clients.TestDbClientItem(forwardServer)
	} else if forwardServer.Type == enums.Http.Get().Value {
		err = handler.TestHttpConnect(forwardServer)
	}
	// 更新状态
	status := utils.If(err != nil, "false", "true").(string)
	_ = d.serverModel.ModMap(&forwardServer, map[string]interface{}{"connect_status": status})
	_ = env.Cache.HashSet(constant.ForwardClientPrefix+forwardServer.Id, map[string]interface{}{constant.ForwardClientStatus: status})
	return
}
